home *** CD-ROM | disk | FTP | other *** search
/ CD/PC Actual 31 / PC Actual CD 31.iso / dists / SRC / SLIBEXEC.AA / SLIBEXEC / libexec / bootpd / getif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-22  |  3.0 KB  |  148 lines

  1. /*
  2.  * getif.c : get an interface structure
  3.  *
  4.  *    $Id: getif.c,v 1.6 1997/02/22 14:21:05 peter Exp $
  5.  */
  6.  
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <sys/ioctl.h>
  10.  
  11. #if defined(SUNOS) || defined(SVR4)
  12. #include <sys/sockio.h>
  13. #endif
  14. #ifdef    SVR4
  15. #include <sys/stropts.h>
  16. #endif
  17.  
  18. #include <sys/time.h>        /* for struct timeval in net/if.h */    
  19. #include <net/if.h>                /* for struct ifreq */
  20. #include <netinet/in.h>
  21.  
  22. #ifndef    NO_UNISTD
  23. #include <unistd.h>
  24. #endif
  25. #include <syslog.h>
  26. #include <errno.h>
  27. #include <assert.h>
  28.  
  29. #include "getif.h"
  30. #include "report.h"
  31.  
  32. #ifdef    __bsdi__
  33. #define BSD 43
  34. #endif
  35.  
  36. static struct ifreq ifreq[10];    /* Holds interface configuration */
  37. static struct ifconf ifconf;    /* points to ifreq */
  38.  
  39. static int nmatch();
  40.  
  41. /* Return a pointer to the interface struct for the passed address. */
  42. struct ifreq *
  43. getif(s, addrp)
  44.     int s;                        /* socket file descriptor */
  45.     struct in_addr *addrp;        /* destination address on interface */
  46. {
  47.     int maxmatch;
  48.     int len, m, incr;
  49.     struct ifreq *ifrq, *ifrmax;
  50.     struct sockaddr_in *sip;
  51.     char *p;
  52.  
  53.     /* If no address was supplied, just return NULL. */
  54.     if (!addrp)
  55.         return (struct ifreq *) 0;
  56.  
  57.     /* Get the interface config if not done already. */
  58.     if (ifconf.ifc_len == 0) {
  59. #ifdef    SVR4
  60.         /*
  61.          * SysVr4 returns garbage if you do this the obvious way!
  62.          * This one took a while to figure out... -gwr
  63.          */
  64.         struct strioctl ioc;
  65.         ioc.ic_cmd = SIOCGIFCONF;
  66.         ioc.ic_timout = 0;
  67.         ioc.ic_len = sizeof(ifreq);
  68.         ioc.ic_dp = (char *) ifreq;
  69.         m = ioctl(s, I_STR, (char *) &ioc);
  70.         ifconf.ifc_len = ioc.ic_len;
  71.         ifconf.ifc_req = ifreq;
  72. #else    /* SVR4 */
  73.         ifconf.ifc_len = sizeof(ifreq);
  74.         ifconf.ifc_req = ifreq;
  75.         m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf);
  76. #endif    /* SVR4 */
  77.         if ((m < 0) || (ifconf.ifc_len <= 0)) {
  78.             report(LOG_ERR, "ioctl SIOCGIFCONF");
  79.             return (struct ifreq *) 0;
  80.         }
  81.     }
  82.     maxmatch = 7;                /* this many bits or less... */
  83.     ifrmax = (struct ifreq *) 0;/* ... is not a valid match  */
  84.     p = (char *) ifreq;
  85.     len = ifconf.ifc_len;
  86.     while (len > 0) {
  87.         ifrq = (struct ifreq *) p;
  88.         sip = (struct sockaddr_in *) &ifrq->ifr_addr;
  89.         m = nmatch(addrp, &(sip->sin_addr));
  90.         if (m > maxmatch) {
  91.             maxmatch = m;
  92.             ifrmax = ifrq;
  93.         }
  94. #ifndef IFNAMSIZ
  95.         /* BSD not defined or earlier than 4.3 */
  96.         incr = sizeof(*ifrq);
  97. #else
  98.         incr = ifrq->ifr_addr.sa_len + IFNAMSIZ;
  99. #endif
  100.  
  101.         p += incr;
  102.         len -= incr;
  103.     }
  104.  
  105.     return ifrmax;
  106. }
  107.  
  108. /*
  109.  * Return the number of leading bits matching in the
  110.  * internet addresses supplied.
  111.  */
  112. static int
  113. nmatch(ca, cb)
  114.     u_char *ca, *cb;            /* ptrs to IP address, network order */
  115. {
  116.     u_int m = 0;                /* count of matching bits */
  117.     u_int n = 4;                /* bytes left, then bitmask */
  118.  
  119.     /* Count matching bytes. */
  120.     while (n && (*ca == *cb)) {
  121.         ca++;
  122.         cb++;
  123.         m += 8;
  124.         n--;
  125.     }
  126.     /* Now count matching bits. */
  127.     if (n) {
  128.         n = 0x80;
  129.         while (n && ((*ca & n) == (*cb & n))) {
  130.             m++;
  131.             n >>= 1;
  132.         }
  133.     }
  134.     return (m);
  135. }
  136.  
  137. /*
  138.  * Local Variables:
  139.  * tab-width: 4
  140.  * c-indent-level: 4
  141.  * c-argdecl-indent: 4
  142.  * c-continued-statement-offset: 4
  143.  * c-continued-brace-offset: -4
  144.  * c-label-offset: -4
  145.  * c-brace-offset: 0
  146.  * End:
  147.  */
  148.